# frozen_string_literal: true

# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/AbcSize
module DecisionTableSeed
  def self.run
    mock_decision_tables(count: 100, row_range: (20..200), io_size: (2..10))

    create_age_decision_table
  end

  def self.create_age_decision_table
    rule = Rule::DecisionTable.create! name: 'Age decision table'
    entity = rule.create_draft_entity!(
      type: 'RuleEntity::DecisionTable',
      stage: RuleEntity::Stage::DRAFT,
      status: RuleEntity::Status::CREATED,
      policy: RuleEntity::Policy::FIRST
    )
    entity.create_rule_schema! schema: age_schema

    variable_index = 0
    column_types = []
    entity.schema.input_variables.each do |input|
      if input.name.eql?('age')
        input.decision_table_headers.create!(
          decision_table: entity,
          name: 'Minimum Age',
          type_method: input.variable_type.type_methods.find_by(name: '>='),
          ordinal: variable_index
        )
        column_types[variable_index] = input.variable_type.name
        variable_index += 1

        input.decision_table_headers.create!(
          decision_table: entity,
          name: 'Maximum Age',
          type_method: input.variable_type.type_methods.find_by(name: '<'),
          ordinal: variable_index
        )
      else
        input.decision_table_headers.create!(
          decision_table: entity,
          name: "#{input.name} column",
          type_method: input.variable_type.type_methods.find_by(name: '='),
          ordinal: variable_index
        )
      end
      column_types[variable_index] = input.variable_type.name
      variable_index += 1
    end

    entity.schema.output_variables.each do |output|
      output.decision_table_headers.create!(
        decision_table: entity,
        name: "#{output.name} column",
        type_method: output.variable_type.type_methods.find_by(name: '='),
        ordinal: variable_index
      )
      column_types[variable_index] = output.variable_type.name
      variable_index += 1
    end

    datas = [
      [0, 3, '婴儿'],
      [3, 7, '童年'],
      [7, 17, '骚年'],
      [17, 35, '青年'],
      [35, 60, '中年'],
      [60, 200, '老年']
    ]

    column_types.map! { |type_name| DecisionTableCell.dt_column_name(type_name) }
    datas.each_with_index do |row_data, row|
      decision_table_row = entity.decision_table_rows.create!(ordinal: row)
      row_data.each_with_index do |value, col|
        decision_table_row.decision_table_cells.create!(
          ordinal: col,
          column_types[col] => value
        )
      end
    end
  end

  def self.mock_decision_tables(count: 10, row_range: (100..200), io_size: (2..5))
    count.times do
      mock_single_decision_table(row_range: row_range, io_size: io_size)
    end
  end

  def self.mock_single_decision_table(row_range: (100..200), io_size: (2..5))
    Rails.logger.info "#{__method__}, start, row_range[#{row_range}], io_size[#{io_size}]."

    ApplicationRecord.transaction do
      schema_name = generate_name
      schema = Schema.create!(
        name: schema_name,
        description: "#{schema_name} description."
      )

      now_time = Time.current
      variable_attrs = %i[schema_id name variable_type_id ordinal io_type required default_value created_at updated_at]
      SchemaVariable.bulk_insert(*variable_attrs) do |worker|
        SchemaVariable::IoType.each_value do |io_type|
          rand(io_size).times do |index|
            variable_name = generate_name
            variable_name = variable_name.gsub(/[^a-zA-Z0-9]/, '_').sub(/^/, "#{io_type.downcase}_").to(60)

            worker.add(
              schema_id: schema.id,
              name: variable_name,
              variable_type_id: variable_type_map['string'].id,
              ordinal: index,
              io_type: io_type,
              required: true,
              default_value: nil,
              created_at: now_time,
              updated_at: now_time
            )
          end
        end
      end

      rule_name = generate_name
      rule = Rule.create!(
        name: rule_name,
        type: Rule::DecisionTable,
        description: "#{rule_name} description"
      )
      decision_table = rule.create_draft_entity!(
        type: RuleEntity::DecisionTable,
        status: RuleEntity::Status::CREATED,
        stage: RuleEntity::Stage::DRAFT,
        policy: RuleEntity::Policy::FIRST,
        version: 0,
        schema: schema
      )

      # decision table headers
      schema.schema_variables.each_with_index do |variable, index|
        decision_table.decision_table_headers.create!(
          schema_variable: variable,
          name: "Column #{variable.name}",
          type_method: type_methods_map['string']['='],
          ordinal: index
        )
      end

      # decision table content
      column_size = schema.schema_variables.count

      cell_attrs = %i[decision_table_row_id ordinal str_value created_at updated_at]
      DecisionTableCell.bulk_insert(*cell_attrs) do |worker|
        rand(row_range).times do |index|
          row = decision_table.decision_table_rows.create!(ordinal: index)

          column_size.times do |col_index|
            worker.add(
              decision_table_row_id: row.id,
              ordinal: col_index,
              str_value: generate_name,
              created_at: now_time,
              updated_at: now_time
            )
          end
        end
      end
    end

    Rails.logger.info "#{__method__}, end."
  end

  def self.age_schema
    SchemaSeed.age_schema
  end

  def self.generate_name
    Faker::Name.unique.name
  end

  def self.variable_type_map
    @variable_type_map ||= VariableType.all.index_by(&:name)
  end

  def self.type_methods_map
    @type_methods_map ||= VariableType.all.map do |type|
      [type.name, type.type_methods.index_by(&:name)]
    end.to_h
  end
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/MethodLength
